home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Periodicals / develop / develop Issue 6 / develop 6 code / TCP / NewsWatcher / NewsWatcher 2.0d15 source / source / smtp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-28  |  6.4 KB  |  249 lines  |  [TEXT/KAHL]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     smtp.c
  4.  
  5.     This module handles all transactions with SMTP servers.
  6.     
  7.     Portions copyright © 1990, Apple Computer.
  8.     Portions copyright © 1993, Northwestern University.
  9.  
  10. ----------------------------------------------------------------------------*/
  11.  
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15. #include "MacTCPCommonTypes.h"
  16. #include "TCPPB.h"
  17.  
  18. #include "glob.h"
  19. #include "dlgutil.h"
  20. #include "smtp.h"
  21. #include "tcp.h"
  22. #include "util.h"
  23.  
  24.  
  25. /* global variables */
  26.  
  27. static char *gBuffer;     /* RecvData buffer */
  28.  
  29.  
  30.  
  31. /*  GetSMTPAddr is called to get the mail server IP address,
  32.     given its name from the preferences file.
  33. */
  34.  
  35. static Boolean GetSMTPAddr (unsigned long *addr)
  36. {
  37.     OSErr err;
  38.     
  39.     p2cstr(gPrefs.mailServerName);
  40.     err = IPNameToAddr((char*)gPrefs.mailServerName, addr);
  41.     c2pstr((char*)gPrefs.mailServerName);
  42.     if (err != noErr) {
  43.         if (err != -1) ErrorMessage("Could not get mail server address.");
  44.         return false;
  45.     }
  46.     return true;
  47. }
  48.  
  49.  
  50. /*    RcptMsg determines the recipients of the message and sends commands
  51.     to the SMTP server specifying these people as recipients.
  52. */
  53.  
  54. static Boolean RcptMsg (char *text, unsigned short tLength, 
  55.     unsigned long stream, char *header)
  56. {
  57.     Ptr current,current2,current3,lineEnd,textEnd;
  58.     CStr255 sendData[4];
  59.     unsigned short length,hdrLen,len;
  60.     Boolean foundHeader;
  61.     OSErr err;
  62.     
  63.     strcpy(sendData[0],"RCPT TO:<");
  64.     strcpy(sendData[2],">");
  65.     strcpy(sendData[3],CRLF);
  66.  
  67.     /* Find the header line. */
  68.     
  69.     current = text;
  70.     hdrLen = strlen(header);
  71.     textEnd = text + tLength;
  72.     foundHeader = false;
  73.     while (!foundHeader && current < textEnd && *current != CR) {
  74.         if (strncasecmp(current,header,hdrLen) == 0) {
  75.             foundHeader = true;
  76.         } else {
  77.             while (current < textEnd && *current != CR) current++;
  78.             current += 2;
  79.         }
  80.     }
  81.     if (!foundHeader) return true;
  82.     
  83.     /* Find the end of the header line. */
  84.     
  85.     current += hdrLen;
  86.     if (current >= textEnd) return true;
  87.     for (lineEnd = current; lineEnd < textEnd && *lineEnd != CR; lineEnd++);
  88.     if (lineEnd >= textEnd) return true;
  89.     
  90.     /* Send a RCPT TO command for each address in the header line.
  91.        Addresses are delimited by commas, and may be in any of the
  92.        forms specified in RFC 1036:
  93.        
  94.                addr
  95.             addr (name)
  96.             name <addr>
  97.     */
  98.     
  99.     while (current < lineEnd) {
  100.         while (current < lineEnd && *current == ' ') current++;
  101.         current2 = current;
  102.         while (current2 < lineEnd && *current2 != ',') current2++;
  103.         current3 = current2 - 1;
  104.         while (current3 > current && *current3 == ' ') current3--;
  105.         if (current3 > current) {
  106.             if (*current3 == ')') {
  107.                 current3--;
  108.                 while (current3 > current && *current3 != '(') current3--;
  109.                 current3--;
  110.                 while (current3 > current && *current3 == ' ') current3--;
  111.             } else if (*current3 == '>') {
  112.                 current3--;
  113.                 while (current3 > current && *current3 == ' ') current3--;
  114.                 while (current < current3 && *current != '<') current++;
  115.                 current++;
  116.                 while (current < current3 && *current == ' ') current++;
  117.             }
  118.         }
  119.         len = current3 - current + 1;
  120.         if (len > 0 && len < 255) {
  121.             strncpy(sendData[1], current, len);
  122.             sendData[1][len] = 0;
  123.             if ((err = SendMultiData(stream,sendData,4)) != noErr) goto exit1;
  124.             length = kBufLen;
  125.             if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  126.             if (length < 3 || *gBuffer != '2') goto exit2;
  127.         }
  128.         current = current2 + 1;
  129.     }
  130.     
  131.     return true;
  132.  
  133. exit1:
  134.  
  135.     UnexpectedErrorMessage(err);
  136.     return false;
  137.     
  138. exit2:
  139.  
  140.     MailOrFTPServerErrorMessage(gBuffer);
  141.     return false;
  142.     
  143. }
  144.  
  145.  
  146. /*    SendSMTP sends a message through e-mail by contacting the local
  147.     SMTP server and sending the mail.
  148. */
  149.  
  150. Boolean SendSMTP (char *text,unsigned short tLength)
  151. {
  152.     unsigned long stream = 0;
  153.     unsigned short length;
  154.     CStr255 sendData[4];
  155.     unsigned long addr;
  156.     CStr255 commStr;
  157.     OSErr err;
  158.     char *serverCommand = nil;
  159.     
  160.     gBuffer = nil;
  161.     gBuffer = NewPtrClear(kBufLen);
  162.     if ((err = MyMemErr()) != noErr) goto exit1;
  163.     
  164.     if (!GetSMTPAddr(&addr)) goto exit1;
  165.         
  166.     if ((err = CreateStream(&stream,kBufLen)) != noErr) goto exit1;
  167.     if ((err = OpenConnection(stream,addr,kSMTPPort,20)) != noErr) {
  168.         if (err != -1) ErrorMessage("Could not open connection to mail server.");
  169.         goto exit3;
  170.     }
  171.         
  172.     length = kBufLen;
  173.     if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  174.     if (length < 3 || *gBuffer != '2') goto exit2;
  175.     
  176.     strcpy(sendData[0],"HELO ");
  177.     if ((err = GetMyIPName(sendData[1])) != noErr) {
  178.         if ((err = GetMyIPAddrStr(sendData[1])) != noErr) goto exit1;
  179.     }
  180.     strcpy(sendData[2],CRLF);
  181.     serverCommand = "HELO";
  182.     if ((err = SendMultiData(stream,sendData,3)) != noErr) goto exit1;
  183.     length = kBufLen;
  184.     if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  185.     if (length < 3 || *gBuffer != '2') goto exit2;
  186.     
  187.     strcpy(sendData[0],"MAIL FROM:<");
  188.     strcpy(sendData[1],gPrefs.address);
  189.     strcpy(sendData[2],">");
  190.     strcpy(sendData[3],CRLF);
  191.     serverCommand = "MAIL FROM";
  192.     if ((err = SendMultiData(stream,sendData,4)) != noErr) goto exit1;
  193.     length = kBufLen;
  194.     if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  195.     if (length < 3 || *gBuffer != '2') goto exit2;
  196.     
  197.     if (!RcptMsg(text,tLength,stream,"To: ")) goto exit3;
  198.     if (!RcptMsg(text,tLength,stream,"Cc: ")) goto exit3;
  199.     if (!RcptMsg(text,tLength,stream,"Bcc: ")) goto exit3;
  200.     
  201.     strcpy(commStr,"DATA");
  202.     strcat(commStr,CRLF);
  203.     serverCommand = "DATA";
  204.     if ((err = SendData(stream,commStr,6)) != noErr) goto exit1;
  205.     length = kBufLen;
  206.     if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  207.     if (length < 3 || *gBuffer != '3') goto exit2;
  208.  
  209.     if ((err = SendData(stream,text,tLength)) != noErr) goto exit1;
  210.     strcpy(commStr,CRLF);
  211.     strcat(commStr,".");
  212.     strcat(commStr,CRLF);
  213.     if ((err = SendData(stream,commStr,5)) != noErr) goto exit1;
  214.     length = kBufLen;
  215.     if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  216.     if (length < 3 || *gBuffer != '2') goto exit2;
  217.     
  218.     strcpy(commStr,"QUIT");
  219.     strcat(commStr,CRLF);
  220.     serverCommand = "QUIT";
  221.     if ((err = SendData(stream,commStr,6)) != noErr) goto exit1;
  222.     length = kBufLen;
  223.     if ((err = RecvData(stream,gBuffer,&length,true)) != noErr) goto exit1;
  224.     if (length < 3 || *gBuffer != '2') goto exit2;
  225.     
  226.     if ((err = CloseConnection(stream, true)) != noErr) goto exit1;
  227.     if ((err = ReleaseStream(stream)) != noErr) goto exit1;
  228.     MyDisposPtr(gBuffer);
  229.     return true;
  230.     
  231. exit1:
  232.  
  233.     UnexpectedErrorMessage(err);
  234.     goto exit3;
  235.     
  236. exit2:
  237.  
  238.     MailOrFTPServerErrorMessage(gBuffer);
  239.  
  240. exit3:
  241.  
  242.     if (stream != 0) {
  243.         AbortConnection(stream);
  244.         ReleaseStream(stream);
  245.     }
  246.     MyDisposPtr(gBuffer);
  247.     return false;
  248. }
  249.